package com.xixi.core.rpc.server.tcp;

import cn.hutool.core.util.IdUtil;
import com.xixi.core.rpc.RpcApplication;
import com.xixi.core.rpc.model.RpcRequest;
import com.xixi.core.rpc.model.RpcResponse;
import com.xixi.core.rpc.model.ServiceMetaInfo;
import com.xixi.core.rpc.protocol.*;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetSocket;

import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * @author: zxh
 * @date: 2024/8/26 11:22
 * @description: 基于Vert.x的TCP传输（客户端）
 */
public class VertxTcpClient {

	public static RpcResponse doRequest(RpcRequest rpcRequest, ServiceMetaInfo serviceMetaInfo) throws ExecutionException, InterruptedException {
		// 发送TCP请求
		Vertx vertx = Vertx.vertx();
		NetClient netClient = vertx.createNetClient();
		CompletableFuture<RpcResponse> responseFuture = new CompletableFuture<>();
		netClient.connect(serviceMetaInfo.getServicePort(), serviceMetaInfo.getServiceHost(),
				result -> {
					if (result.succeeded()) {
						System.out.println("Connected to TCP server");
						NetSocket socket = result.result();
						// 发送数据
						// 构造消息
						ProtocolMessage<RpcRequest> protocolMessage = new ProtocolMessage<>();
						ProtocolMessage.Header header = new ProtocolMessage.Header();
						header.setMagic(ProtocolConstant.PROTOCOL_MAGIC);
						header.setVersion(ProtocolConstant.PROTOCOL_VERSION);
						header.setSerializer((byte) Objects.requireNonNull(ProtocolMessageSerializerEnum.getEnumByValue(RpcApplication.getRpcConfig().getSerializer())).getKey());
						header.setType((byte) ProtocolMessageTypeEnum.REQUEST.getKey());
						header.setRequestId(IdUtil.getSnowflakeNextId());
						protocolMessage.setHeader(header);
						protocolMessage.setBody(rpcRequest);
						// 编码请求
						try {
							System.out.println("开始代理请求数据编码");
							Buffer encode = ProtocolMessageEncoder.encode(protocolMessage);
							System.out.println("代理请求数据编码完成： " + encode.length());
							socket.write(encode);
						} catch (IOException e) {
							throw new RuntimeException("协议消息编码错误");
						}

						TcpBufferHandlerWrapper bufferHandlerWrapper = new TcpBufferHandlerWrapper(buffer -> {
							try {
								System.out.println("开始代理请求响应解码：" + buffer.length());
								ProtocolMessage<RpcResponse> decode = (ProtocolMessage<RpcResponse>) ProtocolMessageDecoder.decode(buffer);
								System.out.println("代理请求响应解码完成");
								responseFuture.complete(decode.getBody());
							} catch (IOException e) {
								throw new RuntimeException("协议消息解码错误");
							}
						});
						// 接收响应
						/*socket.handler(buffer -> {
							try {
								System.out.println("开始代理请求响应解码：" + buffer.length());
								ProtocolMessage<RpcResponse> decode = (ProtocolMessage<RpcResponse>) ProtocolMessageDecoder.decode(buffer);
								System.out.println("代理请求响应解码完成");
								responseFuture.complete(decode.getBody());
							} catch (IOException e) {
								throw new RuntimeException("协议消息解码错误");
							}
						});*/

						socket.handler(bufferHandlerWrapper);
					} else {
						System.err.println("Failed to connect to TCP server");
					}
				});
		RpcResponse rpcResponse = responseFuture.get();
		netClient.close();
		vertx.close();
		return rpcResponse;
	}

	public void start() {
		// 创建Vert.x实例
		Vertx vertx = Vertx.vertx();

		vertx.createNetClient().connect(8888, "localhost", result -> {
			if (result.succeeded()) {
				System.out.println("Connect to TCP server");
				NetSocket socket = result.result();
				// for (int i = 0; i < 1000; i++) {
					// 发送数据
					Buffer buffer1 = Buffer.buffer();
					String str = "Hello, server! Hello, server! Hello, server! Hello, server!";
					buffer1.appendInt(0);
					buffer1.appendInt(str.getBytes().length);
					buffer1.appendBytes(str.getBytes());
					socket.write(buffer1);
				// }
				// 发送数据
				// socket.write("hello ,server!");
				// 接收响应
				socket.handler(buffer -> {
					System.out.println("Received response from server: " + buffer.toString());
				});
			} else {
				System.out.println("Failed to connect to TCP server");
			}
		});
	}

	public static void main(String[] args) {
		new VertxTcpClient().start();
	}
}
